/*
 *    This file is part of CeluMap.
 *
 *    CeluMap is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    CeluMap is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Copyright 2006, 2007, 2008 Gonzalo Merayo
 *    gonzalo (at) celumap.com.ar
 *    www.celumap.com.ar
 *
 */

package panel;

import editor.Editor;
import figures.Figure;
import figures.FigureIterator;
import figures.basic.ImageFigure;
import geometry.Matrix;
import geometry.MovingTransform;
import geometry.Rectangle;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.LinkedList;

import javax.swing.JPanel;

import map.Map;

public class MapPanel extends JPanel {

	private static final long serialVersionUID = -2158814982308952579L;
	private Map map = null;
	private MovingTransform transform = new MovingTransform();
	private Editor tool = null;
	private Image imap = null;
	boolean show_image = true;
	boolean show_map = true;
	public MapPanel(){
		super();
	}
	
	public void init(){
		setFocusable(true);
		addComponentListener(new ComponentAdapter(){
			public void componentResized(ComponentEvent evt){
				transform.setScreenCentre(getWidth()/2, getHeight()/2);
				FigureIterator i =map.getFigures(null);
				Rectangle r = null;
				while(i.hasNext()){
					if(r==null)
						r = new Rectangle(i.next().getBoundingBox());
					else
						r.unite(i.next().getBoundingBox());
				}
				if(r!=null)
					transform.adjust(r, getWidth(), getHeight());
			}
		});
		addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e) {
				if((e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK)!=0){
					transform.translate(getWidth()/2-e.getX(),getHeight()/2-e.getY());
					repaint();
				}
			}
		});
		addMouseWheelListener(new MouseWheelListener(){
			public void mouseWheelMoved(MouseWheelEvent e) {
				if(e.getWheelRotation()<0)
					transform.zoom((Matrix.pfshift*5)/4);
				else
					transform.zoom((Matrix.pfshift*3)/4);
				repaint();
			}});
		addKeyListener(new KeyListener(){
			public void keyTyped(KeyEvent e) {
			}
			public void keyReleased(KeyEvent e) {
			}
			public void keyPressed(KeyEvent e) {
				int x = 5;
				switch(e.getKeyCode()){
					case KeyEvent.VK_I:
						transform.zoom((Matrix.pfshift*5)/4);
						repaint();
						break;
					case KeyEvent.VK_UP:
						transform.translate(0, x);
						repaint();
						break;
					case KeyEvent.VK_DOWN:
						transform.translate(0, -x);
						repaint();
						break;
					case KeyEvent.VK_LEFT:
						transform.translate(x, 0);
						repaint();
						break;
					case KeyEvent.VK_RIGHT:
						transform.translate(-x, 0);
						repaint();
						break;
					case KeyEvent.VK_O:
						transform.zoom((Matrix.pfshift*3)/4);
						repaint();
						break;
					case KeyEvent.VK_K:
						show_image = ! show_image;
						repaint();
						break;
					case KeyEvent.VK_L:
						show_map = ! show_map;
						repaint();
						break;
				}
			}});		
	}
	public Map getMap() {
		return map;
	}
	public void setMap(Map map) {
		this.map = map;
	}
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		if(show_image && imap!=null)
			g.drawImage(imap, transform.mapX2screen(0, 0), transform.mapY2screen(0, 0), transform.mapX2screen(imap.getWidth(null), imap.getHeight(null)), transform.mapY2screen(imap.getWidth(null), imap.getHeight(null)), 0, 0, imap.getWidth(null), imap.getHeight(null), null);
		if(show_map && map!=null){
			GraphicsProxy gp = new GraphicsProxy(g);
			drawMap(gp, new Rectangle(0,0,getWidth(), getHeight()));
			if(tool!=null)
				tool.toolPaint(g);
		}
	}
	private void drawMap(GraphicsProxy gp, Rectangle area) {
		Rectangle d = new Rectangle();
		transform.screen2map(area, d);
		LinkedList<Figure> l = new LinkedList<Figure>();
		FigureIterator figs = map.getFigures(d);
		while(figs.hasNext()){
			Figure f = figs.next();
			l.add(f);
			if(!(f instanceof ImageFigure))
				f.drawIn(gp, area, transform);
		}
		for(Figure f:l){
			if(f instanceof ImageFigure)
				f.drawIn(gp, area, transform);
		}
		for(Figure f:l){
			if(transform.getZoom()>(Matrix.pfshift/2))
				f.drawVolatileIn(gp, area, transform, false, 0);
		}
	}

	public MovingTransform getTransform() {
		return transform;
	}
	public void setTool(Editor tool) {
		this.tool = tool;
	}

	public void setImap(Image imap) {
		this.imap = imap;
	}
	

}
